﻿using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Bases;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.ContentManagementFramework.SystemFacade.Utilities;
using Fuse8.DomainFramework.BusinessService;
using Fuse8.DomainFramework.Common;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Fuse8.ContentManagementFramework.Web.ApplicationRuntime
{
    public class CmsMembershipService : IMembershipService
    {
        #region Fields

        private CmsUserInformationService _userInformationService = new CmsUserInformationService();
        private CmsUserService _userService = new CmsUserService();
        private CmsUserGroupService _userGroupService = new CmsUserGroupService();

        #endregion Fields

        #region IMembershipService Members

        public virtual int MinPasswordLenght
        {
            get
            {
                return 7;
            }
        }

        public virtual string PasswordRegex
        {
            get
            {
                return @"^.*(?=.{7,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_]).*$";
            }
        }

        public virtual int PasswordHistoryDepth
        {
            get
            {
                return 5;
            }
        }

        public virtual CmsUser CreateUser(string loginName, string userEmail, string userName, bool isSystem, SiteAwareCategory category, string lastname, string password, bool isSendEmail, string locale)
        {
            Guard.ArgumentNotEmpty(loginName, "loginName");
            Guard.ArgumentNotEmpty(userEmail, "userEmail");
            Guard.ArgumentNotEmpty(userName, "userName");

            var result = new CmsUserInformation
            {
                LoggedInUser = new CmsUser
                {
                    LoginName = loginName,
                    UserEmail = userEmail,
                    Firstname = userName,
                    Lastname = lastname,
                    IsSystem = isSystem,
                    SiteCategory = category,
                    Locale =  locale
                },
                IsInitial = string.IsNullOrEmpty(password)
            };

            if (string.IsNullOrEmpty(password))
            {
                var newUserPassword = PasswordGenerator.Generate(MinPasswordLenght);
                result.LoggedInUser.StorePassword(newUserPassword, PasswordHistoryDepth);
            }
            else
            {
                result.LoggedInUser.StorePassword(password, PasswordHistoryDepth);
            }

            _userInformationService.CreateUser(result);

            if (isSendEmail)
            {
                EmailService.Send(new CmsNewUserCreatedEmail(result.LoggedInUser));
            }

            return result.LoggedInUser;
        }

        public void UpdateUser(CmsUser user, bool isSendEmail)
        {
            UpdateUser(user, null, isSendEmail);
        }

        public void UpdateUser(CmsUser user, string newPassword, bool isSendEmail)
        {
            Guard.ArgumentNotNull(user, "user");

            if (!string.IsNullOrEmpty(newPassword))
            {
                user.StorePassword(newPassword, PasswordHistoryDepth);
            }

            _userInformationService.UpdateUser(user);

            if (isSendEmail)
            {
                EmailService.Send(new CmsUserUpdatedEmail(user));
            }
        }

        public void DeleteUser(CmsUser user)
        {
            Guard.ArgumentNotNull(user, "user");

            _userService.Remove(user);
        }

        public virtual bool ValidateUser(string loginName, string password)
        {
            Guard.ArgumentNotEmpty(loginName, "loginName");
            Guard.ArgumentNotEmpty(password, "password");

            bool result = false;

            var userInformation = new CmsUserInformationService().GetUserInformationByLoginName(loginName);
            if ((userInformation != null) && (userInformation.LoggedInUser != null))
            {
                result = userInformation.LoggedInUser.Validate(password, PasswordHistoryDepth);
            }

            return result;
        }

        public void ResetUserPassword()
        {
            throw new NotImplementedException();
        }

        public CmsUserGroup CreateUserGroup(string groupName, bool isSystem, SiteAwareCategory category)
        {
            Guard.ArgumentNotEmpty(groupName, "groupName");

            var result = new CmsUserGroup
            {
                GroupName = groupName,
                IsSystem = isSystem,
                IsEnabled = true,
                SiteCategory = category
            };

            _userGroupService.Add(result);

            return result;
        }

        public void UpdateUserGroup(CmsUserGroup userGroup)
        {
            Guard.ArgumentNotNull(userGroup, "userGroup");

            _userGroupService.Save(userGroup);
        }

        public void DeleteUserGroup(CmsUserGroup userGroup)
        {
            Guard.ArgumentNotNull(userGroup, "userGroup");

            _userGroupService.Remove(userGroup);
        }

        public virtual void AssignToGroups(CmsUser user, IEnumerable<CmsUserGroup> userGroups)
        {
            Guard.ArgumentNotNull(user, "user");
            Guard.ArgumentNotNull(userGroups, "userGroups");

            _userInformationService.AssignToGroups(user.Id, userGroups);
        }

        public virtual void RemoveFromGroups(CmsUser user, IEnumerable<CmsUserGroup> userGroups)
        {
            Guard.ArgumentNotNull(user, "user");
            Guard.ArgumentNotNull(userGroups, "userGroups");

            _userInformationService.RemoveFromGroups(user.Id, userGroups);
        }

        public virtual bool IsUserInGroup(string userName, string userGroupName)
        {
            Guard.ArgumentNotEmpty(userName, "userName");
            Guard.ArgumentNotEmpty(userGroupName, "userGroupName");

            bool result = false;

            var userInformation = new CmsUserInformationService().GetUserInformationByLoginName(userName);
            if ((userInformation != null) && (userInformation.LoggedInUserGroups != null))
            {
                result = userInformation.LoggedInUserGroups.Any(p => p.GroupName.Equals(userGroupName, StringComparison.OrdinalIgnoreCase));
            }

            return result;
        }

        public virtual IEnumerable<CmsUserGroup> GetUserGroups(CmsUser user)
        {
            Guard.ArgumentNotNull(user, "user");

            var userInformation = new CmsUserInformationService().GetUserInformationByLoginName(user.LoginName);

            return userInformation != null ?
                userInformation.LoggedInUserGroups :
                null;
        }

        public virtual IEnumerable<CmsUserGroup> GetAllUserGroups()
        {
            return _userGroupService.FindAll();
        }

        #endregion IMembershipService Members
    }
}